package com.ccteam.fluidmusic.ui.artist

import android.content.res.ColorStateList
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.paging.LoadState
import com.ccteam.fluidmusic.NavMoreMusicDirections
import com.ccteam.fluidmusic.R
import com.ccteam.fluidmusic.databinding.FragmentArtistDetailMusicPagerBinding
import com.ccteam.fluidmusic.databinding.SimpleMusicItemBinding
import com.ccteam.fluidmusic.view.adapters.GlobalDefaultMusicItemAdapter
import com.ccteam.fluidmusic.view.adapters.paging.CustomLoadStateAdapter
import com.ccteam.fluidmusic.view.adapters.paging.PagingAdapter
import com.ccteam.fluidmusic.view.base.LightBounceEdgeEffectFactory
import com.ccteam.fluidmusic.view.bean.METADATA_CHANGED
import com.ccteam.fluidmusic.view.bean.MoreInfoData
import com.ccteam.fluidmusic.ui.MainActivityViewModel
import com.ccteam.fluidmusic.utils.getColor
import com.ccteam.model.music.BITRATE_NO
import com.ccteam.model.music.BITRATE_SQ
import com.ccteam.shared.result.music.DefaultMusicItem
import com.ccteam.shared.utils.NO_PLAYING
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class ArtistDetailMusicPagerFragment : Fragment() {

    private var _binding: FragmentArtistDetailMusicPagerBinding? = null
    private val binding get() = _binding!!

    private val artistDetailMusicViewModel: ArtistDetailMusicViewModel by viewModels()
    private val artistDetailViewModel: ArtistDetailViewModel by viewModels(ownerProducer = {parentFragment ?: this})
    private val mainActivityViewModel: MainActivityViewModel by activityViewModels()

    /**
     * 是否是第一次加载
     * 如果不是第一次启动，则需要在分页数据更新时再次刷新一下数据，否则正在播放内容不会正确进行同步
     */
    private var isFirstLoad: Boolean = true

    @Inject lateinit var lightBounceEdgeEffectFactory: LightBounceEdgeEffectFactory

    companion object {
        @JvmStatic
        fun newInstance(artistId: String): ArtistDetailMusicPagerFragment {
            return ArtistDetailMusicPagerFragment().apply {
                arguments = Bundle().apply {
                    putString("artistId", artistId)
                }
            }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentArtistDetailMusicPagerBinding.inflate(inflater,container,false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        val adapter = ArtistMusicListAdapter(musicItemCallback)
        binding.rvArtistDetailMusic.adapter = adapter.withLoadStateFooter(
            CustomLoadStateAdapter(adapter){
                adapter.retry()
            }
        )

        lightBounceEdgeEffectFactory.applyBounceView(binding.rvArtistDetailMusic,this)
        binding.rvArtistDetailMusic.edgeEffectFactory = lightBounceEdgeEffectFactory

        artistDetailMusicViewModel.artistMusicLiveData.observe(viewLifecycleOwner, {
            // 如果不是第一次加载，而是回退到此界面，则手动刷新一下数据
            if(!isFirstLoad){
                viewLifecycleOwner.lifecycleScope.launch {
                    artistDetailMusicViewModel.refreshNowPlaying()
                    isFirstLoad = true
                }
            }
            adapter.submitData(viewLifecycleOwner.lifecycle,it)
        })
        viewLifecycleOwner.lifecycleScope.launch {
            adapter.loadStateFlow.collectLatest { state ->
                binding.statusView.changeToLoadingStatus(state.refresh is LoadState.Loading)
                binding.statusView.changeToErrorStatus(state.refresh,
                    state.append.endOfPaginationReached && adapter.itemCount < 1)
            }
        }

        binding.statusView.setRetryClickListener {
            artistDetailViewModel.refreshArtistInfo()
            adapter.refresh()
        }
    }

    class ArtistMusicListAdapter(
        private val callback: GlobalDefaultMusicItemAdapter.DefaultMusicItemClickCallback
    ): PagingAdapter<DefaultMusicItem,
            GlobalDefaultMusicItemAdapter.SimpleMusicItemViewHolder, SimpleMusicItemBinding>(DefaultMusicItem.differCallbackSingle) {

        override fun createPagingViewHolder(
            parent: ViewGroup,
            viewType: Int
        ): GlobalDefaultMusicItemAdapter.SimpleMusicItemViewHolder {
            return GlobalDefaultMusicItemAdapter.SimpleMusicItemViewHolder(callback,
                SimpleMusicItemBinding.inflate(LayoutInflater.from(parent.context),parent,false))
        }

        override fun bindPagingItem(
            holder: GlobalDefaultMusicItemAdapter.SimpleMusicItemViewHolder,
            position: Int,
            item: DefaultMusicItem?,
            payloads: MutableList<Any>
        ) {
            var fullRefresh = payloads.isEmpty()

            if(payloads.isNotEmpty()){
                payloads.forEach { payload ->
                    when(payload){
                        METADATA_CHANGED -> {
                            // 当前播放内容更改时进行的局部UI更新
                            updateActiveItem(holder,item as DefaultMusicItem)
                        }
                        else ->
                            fullRefresh = true
                    }
                }
            }

            // 完整更新列表内容
            if(fullRefresh) {
                item?.let {
                    updateDefaultMusicItem(holder,it,position)
                }
            }
        }

        private fun updateDefaultMusicItem(holder: GlobalDefaultMusicItemAdapter.SimpleMusicItemViewHolder,
                                           item: DefaultMusicItem,position: Int){
            holder.item = item
            holder.binding.tvMusicTitle.text = item.title
            holder.binding.tvMusicSubtitle.text = item.subtitle
            holder.binding.tvCount.text = (position.plus(1)).toString()
            holder.binding.tvBitrate.isVisible = item.bitrate == BITRATE_SQ
            // 设置播放项状态（播放 or 未播放）
            updateActiveItem(holder,item)
            // 如果当前内容为可播放，但是却没有音乐，说明是特殊情况，不显示更多按钮
            holder.binding.btnMore.isVisible = !(item.playable && item.bitrate == BITRATE_NO)
        }

        private fun updateActiveItem(holder: GlobalDefaultMusicItemAdapter.SimpleMusicItemViewHolder, item: DefaultMusicItem){
            when(item.playbackRes){
                // 如果没有播放状态的项，则是默认状态
                NO_PLAYING ->{
                    holder.binding.root.isEnabled = item.playable
                    holder.binding.btnMore.isEnabled = item.playable
                    if(item.playable){
                        holder.binding.tvMusicTitle.setTextColor(MaterialColors.getColor(holder.binding.tvMusicTitle, R.attr.colorOnSurface))
                        holder.binding.tvMusicSubtitle.setTextColor(holder.binding.tvMusicSubtitle.getColor(R.color.defaultTextColor))
                        holder.binding.btnMore.iconTint = ColorStateList.valueOf(MaterialColors.getColor(holder.binding.tvMusicTitle, R.attr.colorOnSurface))
                    } else {
                        holder.binding.tvMusicTitle.setTextColor(holder.binding.tvMusicTitle.getColor(R.color.disableTextColor))
                        holder.binding.tvMusicSubtitle.setTextColor(holder.binding.tvMusicSubtitle.getColor(R.color.disableTextColor))
                        holder.binding.btnMore.iconTint = ColorStateList.valueOf(holder.binding.tvMusicTitle.getColor(R.color.disableTextColor))
                    }
                    holder.binding.ivMusicWave.visibility = View.GONE
                    holder.binding.tvCount.visibility = View.VISIBLE
                }
                else ->{
                    val color =
                        MaterialColors.getColor(holder.binding.tvMusicTitle, R.attr.colorPrimary)
                    holder.binding.tvMusicTitle.setTextColor(color)
                    holder.binding.tvMusicSubtitle.setTextColor(color)
                    holder.binding.ivMusicWave.visibility = View.VISIBLE
                    holder.binding.tvCount.visibility = View.GONE
                }

            }
        }

    }

    private val musicItemCallback = object: GlobalDefaultMusicItemAdapter.DefaultMusicItemClickCallback{
        override fun musicItemClicked(item: DefaultMusicItem) {
            mainActivityViewModel.playMediaId(item.mediaId,artistDetailMusicViewModel.parentId.value,false)
        }

        override fun moreClicked(item: DefaultMusicItem) {
            findNavController().navigate(
                NavMoreMusicDirections.actionGlobalMusicMoreBottomSheetFragment(
                MoreInfoData(artistDetailMusicViewModel.parentId.value!!,item.mediaId,item.title,
                    item.subtitle,false,item.albumId,item.artistInfo,item.albumArtUri,
                    canShare = artistDetailMusicViewModel.isLogin)
            ))
        }

    }
    override fun onDestroyView() {
        super.onDestroyView()

        isFirstLoad = false

        _binding = null
    }
}